﻿using System;
using System.Text;

namespace org.lionsoul.ip2region
{

    /// <summary>
    /// util class 
    /// 
    /// @author chenxin<chenxin619315@gmail.com>
    /// </summary>
    public class Util
    {
        /// <summary>
        /// write specfield bytes to a byte array start from offset
        /// </summary>
        /// <param name="b"> </param>
        /// <param name="offset"> </param>
        /// <param name="v"> </param>
        /// <param name="bytes"> </param>
        public static void write(byte[] b, int offset, long v, int bytes)
        {
            for (int i = 0; i < bytes; i++)
            {
                b[offset++] = (byte)(((long)((ulong)v >> (8 * i))) & 0xFF);
            }
        }

        /// <summary>
        /// write a int to a byte array
        /// </summary>
        /// <param name="b"> </param>
        /// <param name="offet"> </param>
        /// <param name="v"> </param>
        public static void writeIntLong(byte[] b, int offset, long v)
        {
            b[offset++] = (byte)((v >> 0) & 0xFF);
            b[offset++] = (byte)((v >> 8) & 0xFF);
            b[offset++] = (byte)((v >> 16) & 0xFF);
            b[offset] = (byte)((v >> 24) & 0xFF);
        }

        /// <summary>
        /// get a int from a byte array start from the specifiled offset
        /// </summary>
        /// <param name="b"> </param>
        /// <param name="offset"> </param>
        public static long getIntLong(byte[] b, int offset)
        {
            return (((b[offset++] & 0x000000FFL)) | ((b[offset++] << 8) & 0x0000FF00L) | ((b[offset++] << 16) & 0x00FF0000L) | ((b[offset] << 24) & 0xFF000000L));
        }

        /// <summary>
        /// get a int from a byte array start from the specifield offset
        /// </summary>
        /// <param name="b"> </param>
        /// <param name="offset"> </param>
        public static int getInt3(byte[] b, int offset)
        {
            return ((b[offset++] & 0x000000FF) | (b[offset++] & 0x0000FF00) | (b[offset] & 0x00FF0000));
        }

        public static int getInt2(byte[] b, int offset)
        {
            return ((b[offset++] & 0x000000FF) | (b[offset] & 0x0000FF00));
        }

        public static int getInt1(byte[] b, int offset)
        {
            return ((b[offset] & 0x000000FF));
        }

        /// <summary>
        /// string ip to long ip
        /// </summary>
        /// <param name="ip"> </param>
        /// <returns>    long </returns>
        public static long ip2long(string ip)
        {
            string[] p = StringHelperClass.StringSplit(ip, "\\.", true);
            if (p.Length != 4)
            {
                return 0;
            }

            int p1 = (int)((Convert.ToInt32(p[0]) << 24) & 0xFF000000);
            int p2 = ((Convert.ToInt32(p[1]) << 16) & 0x00FF0000);
            int p3 = ((Convert.ToInt32(p[2]) << 8) & 0x0000FF00);
            int p4 = ((Convert.ToInt32(p[3]) << 0) & 0x000000FF);

            return ((p1 | p2 | p3 | p4) & 0xFFFFFFFFL);
        }

        /// <summary>
        /// int to ip string 
        /// </summary>
        /// <param name="ip"> </param>
        /// <returns>    string </returns>
        public static string long2ip(long ip)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append((ip >> 24) & 0xFF).Append('.').Append((ip >> 16) & 0xFF).Append('.').Append((ip >> 8) & 0xFF).Append('.').Append((ip >> 0) & 0xFF);

            return sb.ToString();
        }

        /// <summary>
        /// check the validate of the specifeld ip address
        /// </summary>
        /// <param name="ip"> </param>
        /// <returns>    boolean </returns>
        public static bool isIpAddress(string ip)
        {
            string[] p = StringHelperClass.StringSplit(ip, "\\.", true);
            if (p.Length != 4)
            {
                return false;
            }

            foreach (string pp in p)
            {
                if (pp.Length > 3)
                {
                    return false;
                }
                int val = Convert.ToInt32(pp);
                if (val > 255)
                {
                    return false;
                }
            }

            return true;
        }
    }
}
//----------------------------------------------------------------------------------------
//	Copyright © 2007 - 2012 Tangible Software Solutions Inc.
//	This class can be used by anyone provided that the copyright notice remains intact.
//
//	This class is used to replace most calls to the Java String.split method.
//----------------------------------------------------------------------------------------
internal static class StringHelperClass
{
    //------------------------------------------------------------------------------------
    //	This method is used to replace most calls to the Java String.split method.
    //------------------------------------------------------------------------------------
    internal static string[] StringSplit(string source, string regexDelimiter, bool trimTrailingEmptyStrings)
    {
        string[] splitArray = System.Text.RegularExpressions.Regex.Split(source, regexDelimiter);

        if (trimTrailingEmptyStrings)
        {
            if (splitArray.Length > 1)
            {
                for (int i = splitArray.Length; i > 0; i--)
                {
                    if (splitArray[i - 1].Length > 0)
                    {
                        if (i < splitArray.Length)
                            System.Array.Resize(ref splitArray, i);

                        break;
                    }
                }
            }
        }

        return splitArray;
    }
}